#include "Scene03.h"

Scene03::Scene03(Managers *managers)
{
	this ->managers = managers;

	currentCam = NULL;
}

Scene03::~Scene03(void)
{
	if (framebuffer != NULL)
		delete framebuffer;

	if (orTexture != NULL)
		delete orTexture;

	if (blur != NULL)
		delete blur;

	if (orDepthTexture != NULL)
		delete orDepthTexture;
}

void Scene03::Initialize()
{
	fadeMod = 0.0f;
	fade = 1.0f;
	end_tloFade = 0;
	end_tloFadeMod = 0;
	end1Fade = 0;
	end1FadeMod = 0;
	end2Fade = 0;
	end2FadeMod = 0;
	end3Fade = 0;
	end3FadeMod = 0;

	ZeroMemory(idm, sizeof(float) * 16);
	idm[0] = 1.0f;
	idm[5] = 1.0f;
	idm[10] = 1.0f;
	idm[15] = 1.0f;

	vpSpecular = managers ->vertexShaderMan ->Get("specular");
	fpSpecular = managers ->pixelShaderMan ->Get("specular");
	vpDof = managers ->vertexShaderMan ->Get("dof");
	fpDof = managers ->pixelShaderMan ->Get("dof");
	vpBlur = managers ->vertexShaderMan ->Get("blur");
	fpBlur = managers ->pixelShaderMan ->Get("blur");

	cgpSpotLightPos = cgGetNamedParameter(fpSpecular ->GetProgram(), "spotLightPos");
	cgpSpotLightTargetPos = cgGetNamedParameter(fpSpecular ->GetProgram(), "spotLightTargetPos");
	modelMatrix = cgGetNamedParameter(vpSpecular ->GetProgram(), "modelMatrix");
	cgpFade = cgGetNamedParameter(fpDof ->GetProgram(), "fade");

	passageway =  managers ->modelMan ->Get("scene03");
	doors = new MultiModel(managers ->modelMan ->Get("doors"), "data\\3d\\doors.pos", modelMatrix);
	neons = new MultiModel(managers ->modelMan ->Get("neon"), "data\\3d\\neon_cases.pos", modelMatrix);
	neonCases = new MultiModel(managers ->modelMan ->Get("neon_case"), "data\\3d\\neon_cases.pos", modelMatrix);

	anim = managers ->animMan ->Get("scene03");

	scena3camera1 = managers ->camerasManager ->Get("scena3camera1");
	scena3camera2 = managers ->camerasManager ->Get("scena3camera2");
	scena3camera3 = managers ->camerasManager ->Get("scena3camera3");
	scena3camera4 = managers ->camerasManager ->Get("scena3camera4");
	scena3camera5 = managers ->camerasManager ->Get("scena3camera5");
	scena3camera6 = managers ->camerasManager ->Get("scena3camera6");
	scena3camera7 = managers ->camerasManager ->Get("scena3camera7");
	scena3camera8 = managers ->camerasManager ->Get("scena3camera8");
	
	framebuffer = new Framebuffer();
	framebuffer ->Initialize(1024, 1024, 32);

	orTexture = new Texture(1024, 1024, 32, NULL);
	orTexture ->BindTexture();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	orDepthTexture = new DepthTexture(1024, 1024);

	blur = new Blur(framebuffer, 3, 1, vpBlur, fpBlur);

	currentCam = managers ->camerasManager ->Get("SteerCamera");

	cgGLSetParameter1f(cgpFade, 1.0f);

	SetAnimation();

	/*Mesh **meshes = passageway ->GetMeshes();
	for (int i = 0; i < passageway ->GetMeshCount(); i++)
		anim ->AttachAnimatable(meshes[i]);*/
}

void Scene03::Render(float ms)
{
	fade += fadeMod * (ms / 1000.0f);
	fade = min(1.0f, max(fade, 0.0f));

	cgGLSetParameter1f(cgpFade, fade);

	//currentCam = managers ->camerasManager ->Get("SteerCamera");

	if (currentCam == NULL)
		return;

	vpSpecular ->DoShader();
	fpSpecular ->DoShader();

	framebuffer ->AttachColorTexture(orTexture ->GetId());
	framebuffer ->AttachDepthTexture(orDepthTexture ->GetId());
	framebuffer ->StartRenderToTexture();
	glViewport(0, 0, 1024, 1024);

	anim ->Process(ms);
	anim ->ProcessAnimatables(ms);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//glScalef(1.0f, 1.0f, 1.0f);

	currentCam ->Process(ms);
	currentCam ->SetViewMatrix();

	sm::Vec3 eyePos = currentCam ->GetPosition();

	/*cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpSpecular ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);*/

	vpSpecular ->DoShader();
	fpSpecular ->DoShader();

	cgGLSetParameter3f(cgGetNamedParameter(fpSpecular ->GetProgram(), "lightPosition"), 100, 1000, 100);	
	cgGLSetParameter3f(cgGetNamedParameter(fpSpecular ->GetProgram(), "eyePosition"), eyePos.x, eyePos.y, eyePos.z);
	cgGLSetParameter1f(cgGetNamedParameter(fpSpecular ->GetProgram(), "focalDistance"), currentCam ->GetTargetDistance());

	cgGLSetMatrixParameterfc(modelMatrix, idm);

	//anim ->Render();
	passageway ->Render();

	doors ->Render();
	neons ->Render();
	neonCases ->Render();

	framebuffer ->FinishRenderToTexture();

	blur ->MakeBlur(orTexture ->GetId());

	glDisable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0, 1280, 0, 1024);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glViewport(0, 0, 1280, 1024);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	vpDof ->DoShader();
	fpDof ->DoShader();

	cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpDof ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex0"), orTexture ->GetId());
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex0"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex1"), blur ->GetBlurredTexture(0));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex1"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex2"), blur ->GetBlurredTexture(1));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex2"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex3"), blur ->GetBlurredTexture(2));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex3"));

	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex2f(0, 0);
	glTexCoord2f(1, 0); glVertex2f(1280, 0);
	glTexCoord2f(1, 1); glVertex2f(1280, 1024);
	glTexCoord2f(0, 1); glVertex2f(0, 1024);
	glEnd();

	cgGLDisableProfile(CG_PROFILE_VP30);
	cgGLDisableProfile(CG_PROFILE_FP30);

	end_tloFade += end_tloFadeMod * (ms / 1000.0f);
	end_tloFade = min(1.0f, max(end_tloFade, 0.0f));

	if (end_tloFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glDisable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("end_tlo") ->BindTexture();

		glColor4f(end_tloFade, end_tloFade, end_tloFade, end_tloFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	end1Fade += end1FadeMod * (ms / 1000.0f);
	end1Fade = min(1.0f, max(end1Fade, 0.0f));

	if (end1Fade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("end1") ->BindTexture();

		glColor4f(1, 1, 1, end1Fade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	end2Fade += end2FadeMod * (ms / 1000.0f);
	end2Fade = min(1.0f, max(end2Fade, 0.0f));

	if (end2Fade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("end2") ->BindTexture();

		glColor4f(1, 1, 1, end2Fade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	end3Fade += end3FadeMod * (ms / 1000.0f);
	end3Fade = min(1.0f, max(end3Fade, 0.0f));

	if (end3Fade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("end3") ->BindTexture();

		glColor4f(1, 1, 1, end3Fade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);

	glEnable(GL_DEPTH_TEST);
}

void Scene03::Notify(float time, const char *type, const char *value)
{
	if (strcmp(type, "camera") == 0)
	{
		currentCam = managers ->camerasManager ->Get(value);
	}

	if (strcmp(type, "effect") == 0)
	{
		if (strcmp(value, "fadedown") == 0)
		{
			fadeMod = -1.0f;
		}

		if (strcmp(value, "fadeup") == 0)
		{
			fadeMod = 1.0f;
		}
	}

	if (strcmp(type, "spriteon") == 0)
	{
		if (strcmp(value, "end_tlo") == 0)
			end_tloFadeMod = 1.0f;
		else if (strcmp(value, "end1") == 0)
			end1FadeMod = 1.0f;
		else if (strcmp(value, "end2") == 0)
			end2FadeMod = 1.0f;
		else if (strcmp(value, "end3") == 0)
			end3FadeMod = 1.0f;
	}

	if (strcmp(type, "spriteoff") == 0)
	{
		if (strcmp(value, "end_tlo") == 0)
			end_tloFadeMod = -1.0f;
		else if (strcmp(value, "end1") == 0)
			end1FadeMod = -1.0f;
		else if (strcmp(value, "end2") == 0)
			end2FadeMod = -1.0f;
		else if (strcmp(value, "end3") == 0)
			end3FadeMod = -1.0f;
	}
}

void Scene03::SetLights()
{
	ZeroMemory(lights, sizeof(float) * 3 * 17);

	managers ->lightsManager ->GetCount();

	Light *light;
	sm::Vec3 lightPos;
	sm::Vec3 lightTargetPos;
	char name[1024];

	int lightIndex = 0;

	for (int i = 0; i < managers ->lightsManager ->GetCount(); i++)
	{
		managers ->lightsManager ->Get(i, name, light);

		if (strstr(name, "scena3") != NULL)
		{
			lightPos = light ->GetPosition();
			lightTargetPos = light ->GetTargetPosition();
			lights[(lightIndex * 3) + 0] = lightPos.x;
			lights[(lightIndex * 3) + 1] = lightPos.y;
			lights[(lightIndex * 3) + 2] = lightPos.z;
			lightsTargets[(lightIndex * 3) + 0] = lightTargetPos.x;
			lightsTargets[(lightIndex * 3) + 1] = lightTargetPos.y;
			lightsTargets[(lightIndex * 3) + 2] = lightTargetPos.z;

			lightIndex++;

			anim ->AttachAnimatable(light);
			anim ->AttachAnimatable(light ->GetTarget());
		}
	}

	cgGLSetParameterArray3f(cgpSpotLightPos, 0, 17, lights);	
	cgGLSetParameterArray3f(cgpSpotLightTargetPos, 0, 17, lightsTargets);
}

void Scene03::SetAnimation()
{
	anim ->AttachAnimatable(scena3camera1);
	anim ->AttachAnimatable(scena3camera1 ->GetTarget());
	anim ->AttachAnimatable(scena3camera2);
	anim ->AttachAnimatable(scena3camera2 ->GetTarget());
	anim ->AttachAnimatable(scena3camera3);
	anim ->AttachAnimatable(scena3camera3 ->GetTarget());
	anim ->AttachAnimatable(scena3camera4);
	anim ->AttachAnimatable(scena3camera4 ->GetTarget());
	anim ->AttachAnimatable(scena3camera5);
	anim ->AttachAnimatable(scena3camera5 ->GetTarget());
	anim ->AttachAnimatable(scena3camera6);
	anim ->AttachAnimatable(scena3camera6 ->GetTarget());
	anim ->AttachAnimatable(scena3camera7);
	anim ->AttachAnimatable(scena3camera7 ->GetTarget());
	anim ->AttachAnimatable(scena3camera8);
	anim ->AttachAnimatable(scena3camera8 ->GetTarget());
}

void Scene03::Prepare()
{
	SetLights();
}
